package com.qf.smsplatform.strategy.service.impl;

import com.alibaba.fastjson.JSON;
import com.qf.smsplatform.common.constants.CacheConstants;
import com.qf.smsplatform.common.constants.OperatorConstants;
import com.qf.smsplatform.common.model.StandardSubmit;
import com.qf.smsplatform.strategy.service.Strategy;
import com.qf.smsplatform.strategy.service.api.CacheService;
import com.qf.smsplatform.strategy.utils.CheckMobileOperator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Set;

/**
 * @Author: LeeRui
 * 2021/1/27 下午 9:18
 * 号段补全策略
 **/
@Service(value = "phase")
@Slf4j
public class MobilePhaseStrategy implements Strategy {

    @Autowired
    private CacheService cacheService;

    @Override
    public boolean strategy(StandardSubmit standardSubmit) {
        log.info("【号段补全策略】 号段补全策略开始执行！！！");
        log.info("【号段补全策略】 开始手机号运营商归属判断。。。");
        //通过运营商判断工具进行手机号运营商归属判断
        String mobile = standardSubmit.getDestMobile();
        if (CheckMobileOperator.isChinaMobilePhoneNum(mobile)) {
            //手机号归属移动
            standardSubmit.setOperatorId(OperatorConstants.CHINA_MOBILE);
            System.out.println("移动用户！");
        } else if (CheckMobileOperator.isChinaUnicomPhoneNum(mobile)) {
            //手机号归属联通
            standardSubmit.setOperatorId(OperatorConstants.CHINA_UNICOM);
            System.out.println("联通用户！");
        } else if (CheckMobileOperator.isChinaTelecomPhoneNum(mobile)) {
            //手机号归属电信
            standardSubmit.setOperatorId(OperatorConstants.CHINA_TELECOM);
            System.out.println("电信用户！");
        } else {
            //手机号未知，后期归属全网通
            standardSubmit.setOperatorId(OperatorConstants.CHINA_UNKNOWN);
            System.out.println("全网通用户！");
        }
        log.info("【号段补全策略】 手机号运营商归属判断完毕！！！");
        //-----------------------------------------------------
        //通过缓存判断手机号的省市区域归属,获取到省id和市id
        //封装key  phase常量+手机号前七位
        String substring = mobile.substring(0, 7);
        String key = CacheConstants.CACHE_PREFIX_PHASE + substring;

        //通过key查询缓存中对应的value
        String str = cacheService.get(key);

        //使用，将value分隔为省id和市id
        String[] split = str.split(",");

        //封装省id和市id到submit对象中（目前无法通过省市id判断运营商）
        standardSubmit.setProvinceId(Integer.parseInt(split[0]));
        standardSubmit.setCityId(Integer.parseInt(split[1]));

        //------------------------------------------------------------------
        // 需要查询出当前手机发送短信需要使用客户绑定的哪个通道（Redis查询）
        // 依据手机号的运行商去选择指定的通道，如果没有找到适用的通道，直接选择全网通
        log.info("【号段补全策略】 开始客户信息补全。。。");
        //从redis缓存中获取当前客户绑定的所用通道信息
        Set<String> channels = cacheService.smembers(CacheConstants.CACHE_PREFIX_SMS_CHANNEL + standardSubmit.getClientID());
        //遍历通道信息，根据submit中运营商信息匹配相应的通道
        Boolean flag = false;
        for (String channel : channels) {
            //redis获取的通道信息set集合是JSON字符串，需要反序列化为map类型的key-value映射
            Map<String, Object> map = JSON.parseObject(channel, Map.class);
            //判断比对
            if (standardSubmit.getOperatorId().equals((Integer) map.get("channelType"))) {
                //成功匹配到相应的运营商
                //将standardSubmit进一步封装完善运营商信息
                //下发的源号码srcNumber=spNumber+extendNumber
                String srcNumber = (String) map.get("spNumber") + (String) map.get("extendNumber");
                standardSubmit.setSrcNumber(srcNumber);
                //下发网关ID号，就是运营商通道号
                Integer gatewayID = (Integer) map.get("channelId");
                standardSubmit.setGatewayID(gatewayID);
                //当前短信费用
                Long fee = Long.parseLong(map.get("fee")+"");
                standardSubmit.setFee(fee);
                flag = true;
                //信息封装完成，无需继续遍历，直接跳出循环
                break;
            }
        }
        if (flag){
            log.info("【号段补全策略】 号段补全策略执行完毕，运营商匹配成功！！！");
        }else {
            log.info("【号段补全策略】 号段补全策略执行完毕，运营商匹配失败，自动分配全网通运营商！！！");
        }
        return true;
    }
}
